/*
 * @Date         : 2022-06-15 14:26:28
 * @LastEditTime: 2024-05-23 15:13:47
 * @LastEditors: Liu 2689810937@qq.com
 * @Description  :  与屏幕通信源文件,包含协议解析，数据处理等
 * @FilePath     : \oralight_CFS\template\btn_scan\Protocol.c
 * @FileLog      :
 */
#include "Protocol.h"
regStruct regSt;           /* 寄存器结构体 */
protocolStruct protocolSt; /* 协议结构体 */
addrAndNumStruct addrAndNumSt;
// protocolFunDealStruct protocolFunDealSt; /* 接口函数指针结构体 */

u8 fr_head[3] = {0x62, 0x6c, 0x6d}; //"blm"
u8 fr_end[3] = {0x6d, 0x6c, 0x62};  //"mlb"
                                    // const u8 *fr_head = "blm";//"blm"
                                    // const u8 *fr_end = "mlb";//"mlb"
u16 fr_dataAreaFront_len;            //数据域之前的字节数
u16 fr_dataAreaBack_len;             //数据域之后的字节数
/**
 * @start: **************************************************************
 * @author: chufengsen
 * @functhion:  void protocol_init(void)
 * @description: 协议初始化，创建结构体实例
 * @param {*}
 * @return {*}
 * @end: ****************************************************************
 */
void protocol_init(void)
{
    recv_restart();
    memset(&regSt, 0, sizeof(regSt));
    regSt.regRSIZE = sizeof(regSt.regR);
    regSt.regWSIZE = sizeof(regSt.regW);
    regSt.regRWSIZE = sizeof(regSt.regRW);
    regSt.flashSaveSize = regSt.regWSIZE + regSt.regRWSIZE + 2; // 2为crc字节数
    /* 除数据域之外的长度 */
    fr_dataAreaFront_len = sizeof(protocolSt.addrSt) + sizeof(protocolSt.cmdSt) + sizeof(protocolSt.head) + sizeof(protocolSt.dataAreaLen) + sizeof(protocolSt.dataAreaNum);
    fr_dataAreaBack_len = sizeof(fr_end) + sizeof(protocolSt.crc16);
    // regSt.regRW.ldSwitch = 0xff;
    // printf("front is %hd ",fr_dataAreaFront_len);
    // printf("Back is %hd ",fr_dataAreaBack_len);
}

u8 *find_fr_head_or_fr_end(u8 *findFromBuf, u8 *findBuf, u16 findFromBufLen)
{
    u16 i;
    for (i = 0; i < findFromBufLen; i++)
    {
        if (findFromBuf[i] == findBuf[0] && findFromBuf[i + 1] == findBuf[1] && findFromBuf[i + 2] == findBuf[2])
        {
            return &findFromBuf[i];
        }
    }
    return NULL;
}

// void memmove(u8* dstBuf,u8* srcBuf,u8 len)
// {
//     u8 i;

//     for (i = 0; i < len;i++)
//     {
//         dstBuf[i] = srcBuf[i];
//     }
// }
// void memset(u8 *src,u8 num,u8 len)
// {
//     u8 j;

//     for (j = 0; j < len;j++)
//     {
//         src[j] = num;
//     }
// }
/**
 * @start: **************************************************************
 * @author: chufengsen
 * @functhion:
 * @description:
 * @return {*}
 * @end: ****************************************************************
 */
#define FLASH_SAVE_ADDR 0x0807f800
void user_system_init(void)
{
    // u16 readCount = 10;

    // while (--readCount)
    // {
    //     HAL_Delay(100);
    //     flash_read_buf(FLASH_SAVE_ADDR, (u8 *)&regSt.regW, regSt.flashSaveSize);
    //     if (crc_check((u8 *)&regSt.regW, regSt.flashSaveSize))
    //         break;
    // }
    // if (!readCount) //初始化
    // {
    memset((u8 *)&regSt.regW, 0, regSt.flashSaveSize);
    // regSt.regW.ready = 1;
    // regSt.regRW.aimedLight = 100;
    // regSt.regRW.alarmValueTemp[0] = 650;
    // regSt.regRW.alarmValueTemp[1] = 650;
    // regSt.regRW.alarmValueTemp[2] = 550;
    // regSt.regRW.alarmValueTemp[3] = 550;
    // regSt.regRW.alarmValueTemp[4] = 550;
    // regSt.regRW.alarmValueTemp[5] = 550;
    // regSt.regRW.freq[0] = 4000;
    // regSt.regRW.pulse[0] = 50;
    // regSt.regRW.power[0] = 0;
    // regSt.regRW.fxLdSt[15].aimedLight = 50;
    // regSt.crc16 = crc16((u8 *)&regSt.regW, regSt.flashSaveSize - 2);
    //     flash_write_buf(FLASH_SAVE_ADDR, (u8 *)&regSt.regW, regSt.flashSaveSize);
    // }
}
/**
 * @start: **************************************************************
 * @author: chufengsen
 * @functhion:
 * @description:
 * @param {char} errCode
 * @return {*}
 * @end: ****************************************************************
 */
void serial_recv_response(u8 errCode)
{
    u8 addr;
    u16 crc_16;
    u8 comSendLen = 0;
    if (protocolSt.cmdSt.cmdAck == 1) //如果收到的是应答数据，不需要再回复
        return;
    else
        protocolSt.cmdSt.cmdAck = 1;
    addr = protocolSt.addrSt.desAddr;
    protocolSt.addrSt.desAddr = protocolSt.addrSt.srcAddr;
    protocolSt.addrSt.srcAddr = addr;
    protocolSt.cmdSt.cmdErrCode = errCode;
    memmove(&protocolSt.dataArea[protocolSt.dataAreaLen], fr_end, sizeof(fr_end));
    comSendLen = protocolSt.dataAreaLen + fr_dataAreaFront_len + sizeof(fr_end);
    crc_16 = crc16((u8 *)&protocolSt, comSendLen);
    comSendLen -= fr_dataAreaFront_len;
    protocolSt.dataArea[comSendLen] = crc_16;
    protocolSt.dataArea[comSendLen + 1] = crc_16 >> 8;
#if (USE_FREERTOS)
#include "FreeRTOS.h"
#include "task.h"
    extern xQueueHandle serialMsgQueue;
    xQueueSend(serialMsgQueue, &protocolSt, 0);
#else
    u2_send_bytes((u8 *)&protocolSt, (protocolSt.dataAreaLen + fr_dataAreaFront_len + fr_dataAreaBack_len));
#endif
}
/**
 * @start: **************************************************************
 * @author: chufengsen
 * @functhion:  void protocol_recv_deal(void)
 * @description: 接收数据协议解析
 * @param {*}
 * @return {*}
 * @end: ****************************************************************
 */
u8 responseDataAreaBuf[DATA_AREA_SIZE] = {0};
/* #####################################宏定义区####################################### */
/* 宏定义赋值应答数据域中的regaddr和num */
#define GET_RES_WRITE_REGADDR_REGNUM                              \
    /* 赋值寄存器地址 */                                   \
    responseDataAreaBuf[protocolSt.dataAreaLen++] = regAddr >> 8; \
    responseDataAreaBuf[protocolSt.dataAreaLen++] = regAddr;      \
    /* 赋值寄存器个数 */                                   \
    responseDataAreaBuf[protocolSt.dataAreaLen++] = regNum;
#define GET_RES_READ_REGADDR_REGNUM                                            \
    /* 赋值寄存器地址 */                                                \
    responseDataAreaBuf[protocolSt.dataAreaLen++] = regAddr >> 8;              \
    responseDataAreaBuf[protocolSt.dataAreaLen++] = regAddr;                   \
    /* 赋值寄存器个数,读寄存器时地址无效情况下regnum为0 */ \
    responseDataAreaBuf[protocolSt.dataAreaLen++] = 0;
/* ##################################################################################### */

u8 protocol_recv_deal(void)
{
    u8 errCode = ERR_NONE;
    /* 功能码判断 */
    switch (protocolSt.cmdSt.cmdCode)
    {
    case 0x3:                             /* 只读 */
        if (protocolSt.cmdSt.cmdAck == 1) //应答数据处理
        {
            if (protocolSt.cmdSt.cmdErrCode != ERR_NONE)
                return protocolSt.cmdSt.cmdErrCode;
            else
            {
                protocolSt.dataAreaLen = 0;
                errCode = protocol_readOnlyCmdDataArea_deal(); //将读到的数据写入寄存器
                if (errCode != ERR_NONE)
                    break;
            }
        }
        else
        {
            if (protocolSt.dataAreaLen != protocolSt.dataAreaNum * 3)
                return ERR_LEN;
            protocolSt.dataAreaLen = 0;
            errCode = protocol_readCmdDataArea_deal(); //返回要读取的寄存器数据
            if (errCode != ERR_NONE)
                break;
        }
        memmove(protocolSt.dataArea, responseDataAreaBuf, protocolSt.dataAreaLen);
        break;
    case 0x6:                             /* 读写和只写 */
        if (protocolSt.cmdSt.cmdAck == 1) //如果是应答数据，直接返回收到的错误码
            return protocolSt.cmdSt.cmdErrCode;
        if (protocolSt.dataAreaLen != protocolSt.dataAreaNum * 5)
        {
            errCode = ERR_LEN;
            return errCode;
        }
        protocolSt.dataAreaLen = 0;
        errCode = protocol_writeCmdDataArea_deal();
        if (errCode != ERR_NONE)
            break;
        memmove(protocolSt.dataArea, responseDataAreaBuf, protocolSt.dataAreaLen);
        break;
    default:
        return ERR_CODE;
    }
    return errCode;
}
/**
 * @start: **************************************************************
 * @author: chufengsen
 * @functhion:  u8 protocol_readCmdDataArea_deal(void)
 * @description: 读命令的应答处理，此函数根据读命令中的寄存器地址和个数，获取数据并填入到responseDataAreaBuf中
 * @return {*}
 * @end: ****************************************************************
 */
u8 protocol_readCmdDataArea_deal(void)
{
    u8 i;
    u8 *pDataArea = protocolSt.dataArea;
    u16 regAddr;
    u8 regNum, regOffset;
    u8 *pRegStAddr = NULL;
    u8 errCode = ERR_NONE;
    u8 j = 0;
    for (i = 0; i < protocolSt.dataAreaNum; i++)
    {
        regAddr = ((unsigned short)*pDataArea << 8) + *(pDataArea + 1);
        pDataArea += 2;
        regNum = *pDataArea++;
        if (regAddr >= 0x1000 && regAddr < 0x2000) /* 读写寄存器组 */
        {
            /* 获取读结构体首地址 */
            pRegStAddr = (u8 *)&regSt.regRW;
            regOffset = (regAddr - 0x1000) * 2;
            /* 地址无效 */
            if (regOffset > regSt.regRWSIZE)
            {
                GET_RES_READ_REGADDR_REGNUM;
                errCode = ERR_REG;
                continue;
            }
        }
        else if (regAddr >= 0x2000 && regAddr < 0x3000) /* 只读寄存器组 */
        {
            /* 获取读结构体首地址 */
            pRegStAddr = (u8 *)&regSt.regR;
            regOffset = (regAddr - 0x2000) * 2;
            /* 地址无效 */
            if (regOffset > regSt.regRSIZE)
            {
                GET_RES_READ_REGADDR_REGNUM;
                errCode = ERR_REG;
                continue;
            }
        }
        else
        {
            /* 地址无效 */
            GET_RES_READ_REGADDR_REGNUM;
            errCode = ERR_REG;
            continue;
        }
        GET_RES_WRITE_REGADDR_REGNUM;
        /* 赋值寄存器数据 */
        memmove(&responseDataAreaBuf[protocolSt.dataAreaLen], pRegStAddr + regOffset, regNum * 2);
        protocolSt.dataAreaLen += regNum * 2;
    }
    return errCode;
}

void bigSwapSmall(u8 *inputPtr, u16 len)
{
    u8 outputPtr;
    u16 i;

    for (i = 0; i < len; i++)
    {
        outputPtr = inputPtr[2 * i];
        inputPtr[2 * i] = inputPtr[2 * i + 1];
        inputPtr[2 * i + 1] = outputPtr;
    }
    // memmove(inputPtr, outputPtr, len*2);
}

u8 protocol_readOnlyCmdDataArea_deal(void)
{
    u8 i;
    u8 *pDataArea = protocolSt.dataArea;
    u16 regAddr, regNum;
    u8 errCode = ERR_NONE;
    u8 *pRegStAddr = NULL;

    // printf("protocolSt.dataAreaNum:%bd",protocolSt.dataAreaNum);
    for (i = 0; i < protocolSt.dataAreaNum; i++)
    {
        regAddr = ((u16)*pDataArea << 8) + *(pDataArea + 1);
        pDataArea += 2;
        regNum = *pDataArea++;
        
        if (regAddr >= 0x1000 && regAddr < 0x2000) /* 读写寄存器组 */
        {
            /* 地址无效 */
            if ((regAddr - 0x1000) * 2 > regSt.regRWSIZE)
            {
                GET_RES_WRITE_REGADDR_REGNUM;
                pDataArea += regNum * 2;
                errCode = ERR_REG;
                continue;
            }
            // printf("regAddr:%hd",regAddr);
            // printf("regNum:%hd",regNum);
            pRegStAddr = (u8 *)&regSt.regRW + (regAddr - 0x1000) * 2;
            bigSwapSmall(pDataArea, regNum);
            memmove(pRegStAddr, pDataArea, regNum * 2);
            sys_write_vp(regAddr, pDataArea, regNum);
            pDataArea += regNum * 2;
        }
        else if (regAddr >= 0x2000 && regAddr < 0x3000) /* 只读寄存器组 */
        {
            /* 地址无效 */
            if ((regAddr - 0x2000) * 2 > regSt.regRSIZE)
            {
                GET_RES_WRITE_REGADDR_REGNUM;
                pDataArea += regNum * 2;
                errCode = ERR_REG;
                continue;
            }
            pRegStAddr = (u8 *)&regSt.regR + (regAddr - 0x2000) * 2;
            bigSwapSmall(pDataArea, regNum);
            memmove(pRegStAddr, pDataArea, regNum * 2);
            sys_write_vp(regAddr, pDataArea, regNum);
            pDataArea += regNum * 2;
        }
        else
        {
            /* 地址无效 */
            GET_RES_WRITE_REGADDR_REGNUM;
            pDataArea += regNum * 2;
            errCode = ERR_REG;
            continue;
        }
        GET_RES_WRITE_REGADDR_REGNUM;
    }
    return errCode;
}
/**
 * @start: **************************************************************
 * @author: chufengsen
 * @functhion:  u8 protocol_writeCmdDataArea_deal(void)
 * @description: 写命令应答处理，将数据写入寄存器中，并填充responseDataAreaBuf
 * @return {*}
 * @end: ****************************************************************
 */
u8 protocol_writeCmdDataArea_deal(void)
{
    u8 i;
    u8 *pDataArea = protocolSt.dataArea;
    u16 regAddr;
    u8 errCode = ERR_NONE, regNum;
    u8 *pRegStAddr = NULL;

    for (i = 0; i < protocolSt.dataAreaNum; i++)
    {
        regAddr = ((unsigned short)*pDataArea << 8) + *(pDataArea + 1);
        pDataArea += 2;
        regNum = *pDataArea++;

        // printf ("regAddr is %hd",regAddr);
        if (regAddr >= 0x1000 && regAddr < 0x2000) /* 读写寄存器组 */
        {
            /* 地址无效 */
            if ((regAddr - 0x1000) * 2 > regSt.regRWSIZE)
            {
                GET_RES_WRITE_REGADDR_REGNUM;
                pDataArea += regNum * 2;
                errCode = ERR_REG;
                continue;
            }

            pRegStAddr = (u8 *)&regSt.regRW + (regAddr - 0x1000) * 2;
            bigSwapSmall(pDataArea, regNum);
            sys_write_vp(regAddr, pDataArea, regNum);
            memmove(pRegStAddr, pDataArea, regNum * 2);
            pDataArea += regNum * 2;
        }
        else if (regAddr >= 0x3000 && regAddr < 0x4000) /* 只写寄存器组 */
        {
            /* 地址无效 */
            if ((regAddr - 0x3000) * 2 > regSt.regWSIZE)
            {
                GET_RES_WRITE_REGADDR_REGNUM;
                pDataArea += regNum * 2;
                errCode = ERR_REG;
                continue;
            }
            pRegStAddr = (u8 *)&regSt.regW + (regAddr - 0x3000) * 2;
            bigSwapSmall(pDataArea, regNum);
            sys_write_vp(regAddr, pDataArea, regNum);
            memmove(pRegStAddr, pDataArea, regNum * 2);
            pDataArea += regNum * 2;
        }
        else
        {
            /* 地址无效 */
            GET_RES_WRITE_REGADDR_REGNUM;
            pDataArea += regNum * 2;
            errCode = ERR_REG;
            continue;
        }
        GET_RES_WRITE_REGADDR_REGNUM;
    }
    return errCode;
}
/**
 * @start: **************************************************************
 * @author: chufengsen
 * @functhion:
 * @description:
 * @param {char} *in_buf
 * @param {unsigned short} in_buf_len
 * @return {*}
 * @end: ****************************************************************
 */
u8 crc_check(u8 *in_buf, u16 in_buf_len)
{
    u16 crc, crc_buf;
    u8 crc_h, crc_l;

    crc = crc16(in_buf, in_buf_len - 2);
    crc_h = in_buf[in_buf_len - 1];
    crc_l = in_buf[in_buf_len - 2];
    crc_buf = ((u16)crc_h << 8) + crc_l;
    if (crc == crc_buf)
        return 1;
    else
        return 0;
}
/**
 * @start: **************************************************************
 * @author: chufengsen
 * @functhion:
 * @description:
 * @param {char} *Pushdata
 * @param {unsigned short} length
 * @return {*}
 * @end: ****************************************************************
 */
u16 crc16(u8 *Pushdata, u16 length)
{
    u16 Reg_CRC = 0xffff;
    u16 i, j;
    for (i = 0; i < length; i++)
    {
        Reg_CRC ^= (unsigned short)(*Pushdata++);
        for (j = 0; j < 8; j++)
        {
            if (Reg_CRC & 0x0001)
                Reg_CRC = Reg_CRC >> 1 ^ 0xA001;
            else
                Reg_CRC >>= 1;
        }
    }

    return Reg_CRC;
}

/**
 * @start: **************************************************************
 * @author: chufengsen
 * @functhion:
 * @description:
 * @param {char} errCode
 * @return {*}
 * @end: ****************************************************************
 */
u16 read_reg_value(u16 regAddr)
{
    u16 ret = 0xfefe;
    u8 *pRegStAddr = NULL;
    if (regAddr >= 0x1000 && regAddr < 0x2000) /* 读写寄存器组 */
    {
        if ((regAddr - 0x1000) * 2 > regSt.regRWSIZE)
        {
            return ret;
        }
        else
        {
            pRegStAddr = (u8 *)&regSt.regRW + (regAddr - 0x1000) * 2;
            ret = 0;
            ret = (unsigned short)*pRegStAddr & 0x00ff;
            pRegStAddr++;
            ret |= (unsigned short)*pRegStAddr << 8;
            return ret;
        }
    }
    else if (regAddr >= 0x2000 && regAddr < 0x3000) /* 只读寄存器组 */
    {
        if ((regAddr - 0x2000) * 2 > regSt.regRSIZE)
        {
            return ret;
        }
        else
        {
            pRegStAddr = (u8 *)&regSt.regR + (regAddr - 0x2000) * 2;
            ret = 0;
            ret = (unsigned short)*pRegStAddr & 0x00ff;
            pRegStAddr++;
            ret |= (unsigned short)*pRegStAddr << 8;
            return ret;
        }
    }
    else if (regAddr >= 0x3000 && regAddr < 0x4000) /* 只写寄存器组 */
    {
        if ((regAddr - 0x3000) * 2 > regSt.regWSIZE)
        {
            return ret;
        }
        else
        {
            pRegStAddr = (u8 *)&regSt.regW + (regAddr - 0x3000) * 2;
            ret = 0;
            ret = (unsigned short)*pRegStAddr & 0x00ff;
            pRegStAddr++;
            ret |= (unsigned short)*pRegStAddr << 8;
            return ret;
        }
    }
    else
    {
        return ret;
    }
}
/**
 * @start: **************************************************************
 * @author: chufengsen
 * @functhion:  void protocol_send_reg(u8 code,int ptrNum, ...)
 * @description: 该函数为可变参函数，...为可变参内容
 * 可变参必须至少有一组unsigned short的regaddr和char的regNum，一个regaddr配对一个regNum
 * 比如你想要从寄存器地址0x1000处读1个寄存器数据，你可以这样写：
 *          protocol_send_reg(0x03,0x02,0x1000,0x01);
 * 但如果你想分别从0x1000处读1个寄存器数据和从0x1020处读1个寄存器数据，你可以这样写：
 *          protocol_send_reg(0x03,0x04,0x1000,0x01,0x1020,0x01);
 * @param {char} code    功能码，0x03读  0x06写
 * @param {int} ptrNum 可变参个数
 * @return {*}
 * @end: ****************************************************************
 */
void protocol_send_reg(u8 mcode,
                       u16 regAddr0, u8 regNum0,
                       u16 regAddr1, u8 regNum1,
                       u16 regAddr2, u8 regNum2,
                       u16 regAddr3, u8 regNum3,
                       u16 regAddr4, u8 regNum4,
                       u16 regAddr5, u8 regNum5,
                       u16 regAddr6, u8 regNum6,
                       u16 regAddr7, u8 regNum7,
                       u16 regAddr8, u8 regNum8,
                       u16 regAddr9, u8 regNum9,
                       u8 ptrNum)
{
    u16 crc, regValue, dataAreaCount = 0, i;
    u16 dataAreaNum;
    u8 j = 0;
    u8 *pRegStAddr = NULL;
    /* 获取数据域个数，数据域个数为可变参数的一半 */
    dataAreaNum = ptrNum;

    addrAndNumSt.regAddr[0] = regAddr0;
    addrAndNumSt.regNum[0] = regNum0;
    addrAndNumSt.regAddr[1] = regAddr1;
    addrAndNumSt.regNum[1] = regNum1;
    addrAndNumSt.regAddr[2] = regAddr2;
    addrAndNumSt.regNum[2] = regNum2;
    addrAndNumSt.regAddr[3] = regAddr3;
    addrAndNumSt.regNum[3] = regNum3;
    addrAndNumSt.regAddr[4] = regAddr4;
    addrAndNumSt.regNum[4] = regNum4;
    addrAndNumSt.regAddr[5] = regAddr5;
    addrAndNumSt.regNum[5] = regNum5;
    addrAndNumSt.regAddr[6] = regAddr6;
    addrAndNumSt.regNum[6] = regNum6;
    addrAndNumSt.regAddr[7] = regAddr7;
    addrAndNumSt.regNum[7] = regNum7;
    addrAndNumSt.regAddr[8] = regAddr8;
    addrAndNumSt.regNum[8] = regNum8;
    addrAndNumSt.regAddr[9] = regAddr9;
    addrAndNumSt.regNum[9] = regNum9;

    memset((u8 *)&protocolSt, 0, sizeof(protocolSt));
    protocolSt.head[0] = 0x62;
    protocolSt.head[1] = 0x6c;
    protocolSt.head[2] = 0x6d;
    protocolSt.addrSt.srcAddr = MAIN_BOARD_ADDR;
    protocolSt.addrSt.desAddr = MAIN_ADDR;
    protocolSt.cmdSt.cmdCode = mcode;
    protocolSt.cmdSt.cmdAck = 0;
    protocolSt.cmdSt.cmdErrCode = 0;
    protocolSt.dataAreaNum = dataAreaNum;
    /* 如果是读指令 */
    if (0x03 == protocolSt.cmdSt.cmdCode)
    {
        protocolSt.dataAreaLen = 3 * dataAreaNum;
        dataAreaCount = 0;
        for (i = 0; i < dataAreaNum; i++)
        {
            protocolSt.dataArea[dataAreaCount++] = addrAndNumSt.regAddr[i] >> 8;
            protocolSt.dataArea[dataAreaCount++] = addrAndNumSt.regAddr[i];
            protocolSt.dataArea[dataAreaCount++] = addrAndNumSt.regNum[i];
        }
        protocolSt.dataArea[dataAreaCount++] = 0x6d;
        protocolSt.dataArea[dataAreaCount++] = 0x6c;
        protocolSt.dataArea[dataAreaCount++] = 0x62;
        bigSwapSmall((u8*)&protocolSt.dataAreaLen,1);
        crc = crc16((u8 *)&protocolSt, dataAreaCount + fr_dataAreaFront_len);
        protocolSt.dataArea[dataAreaCount++] = crc;
        protocolSt.dataArea[dataAreaCount++] = crc >> 8;
    }
    /* 如果是写指令 */
    else if (0x06 == protocolSt.cmdSt.cmdCode)
    {
        protocolSt.dataAreaLen = 0;
        dataAreaCount = 0;
        for (i = 0; i < dataAreaNum; i++)
        {
            protocolSt.dataAreaLen += (3 + addrAndNumSt.regNum[i] * 2);
            protocolSt.dataArea[dataAreaCount++] = addrAndNumSt.regAddr[i] >> 8;
            protocolSt.dataArea[dataAreaCount++] = addrAndNumSt.regAddr[i];
            protocolSt.dataArea[dataAreaCount++] = addrAndNumSt.regNum[i];
            for (j = 0; j < addrAndNumSt.regNum[i]; j++)
            {
                sys_read_vp(addrAndNumSt.regAddr[i] + j, (u8 *)&regValue, 1);

                if (addrAndNumSt.regAddr[i] >= 0x1000 && addrAndNumSt.regAddr[i] < 0x2000) /* 读写寄存器组 */
                {
                    pRegStAddr = (u8 *)&regSt.regRW + (addrAndNumSt.regAddr[i] + j - 0x1000) * 2;
                    // printf("pRegStAddr is %d\r\n", pRegStAddr);
                    // printf("regRW is %d\r\n", (u8 *)&regSt.regRW);
                    memmove(pRegStAddr, (u8*)&regValue, 2);
                }
                else if (addrAndNumSt.regAddr[i] >= 0x3000 && addrAndNumSt.regAddr[i] < 0x4000) /* 只写寄存器组 */
                {
                    pRegStAddr = (u8 *)&regSt.regW + (addrAndNumSt.regAddr[i] + j - 0x3000) * 2;
                    memmove(pRegStAddr, (u8*)&regValue, 2);
                }
                // printf("regAddr is %hd,regValue is %hd,aim:%hd\r\n", addrAndNumSt.regAddr[i] + j, regValue, regSt.regRW.aimedLight);
                // printf("addr:%hd ",addrAndNumSt.regAddr[i] + j);
                // printf("regValue:%hd \r\n",regValue);
                protocolSt.dataArea[dataAreaCount++] = regValue;
                protocolSt.dataArea[dataAreaCount++] = regValue >> 8;
            }
        }
        protocolSt.dataArea[dataAreaCount++] = 0x6d;
        protocolSt.dataArea[dataAreaCount++] = 0x6c;
        protocolSt.dataArea[dataAreaCount++] = 0x62;
        // printf("dataAreaCount is %hd", dataAreaCount);
        // printf("fr_dataAreaFront_len is %bd", fr_dataAreaFront_len);
        bigSwapSmall((u8*)&protocolSt.dataAreaLen,1);
        crc = crc16((u8 *)&protocolSt, dataAreaCount + fr_dataAreaFront_len);
        protocolSt.dataArea[dataAreaCount++] = crc;
        protocolSt.dataArea[dataAreaCount++] = crc >> 8;
    }
    else
    {
        protocolSt.dataAreaLen = 0;
        dataAreaCount = 0;
        protocolSt.dataArea[dataAreaCount++] = 0x6d;
        protocolSt.dataArea[dataAreaCount++] = 0x6c;
        protocolSt.dataArea[dataAreaCount++] = 0x62;
        bigSwapSmall((u8*)&protocolSt.dataAreaLen,1);
        crc = crc16((u8 *)&protocolSt, dataAreaCount + fr_dataAreaFront_len);
        protocolSt.dataArea[dataAreaCount++] = crc;
        protocolSt.dataArea[dataAreaCount++] = crc >> 8;
    }
    
    u2_send_bytes((u8 *)&protocolSt, dataAreaCount + fr_dataAreaFront_len);
}
void protocol_send_RFID(u8 mcode,
                       u16 regAddr0, u8 regNum0,
                       u16 regAddr1, u8 regNum1,
                       u16 regAddr2, u8 regNum2,
                       u16 regAddr3, u8 regNum3,
                       u16 regAddr4, u8 regNum4,
                       u16 regAddr5, u8 regNum5,
                       u16 regAddr6, u8 regNum6,
                       u16 regAddr7, u8 regNum7,
                       u16 regAddr8, u8 regNum8,
                       u16 regAddr9, u8 regNum9,
                       u8 ptrNum)
{
    u16 crc, regValue, dataAreaCount = 0, i;
    u16 dataAreaNum;
    u8 j = 0;
    u8 *pRegStAddr = NULL;
    /* 获取数据域个数，数据域个数为可变参数的一半 */
    dataAreaNum = ptrNum;

    addrAndNumSt.regAddr[0] = regAddr0;
    addrAndNumSt.regNum[0] = regNum0;
    addrAndNumSt.regAddr[1] = regAddr1;
    addrAndNumSt.regNum[1] = regNum1;
    addrAndNumSt.regAddr[2] = regAddr2;
    addrAndNumSt.regNum[2] = regNum2;
    addrAndNumSt.regAddr[3] = regAddr3;
    addrAndNumSt.regNum[3] = regNum3;
    addrAndNumSt.regAddr[4] = regAddr4;
    addrAndNumSt.regNum[4] = regNum4;
    addrAndNumSt.regAddr[5] = regAddr5;
    addrAndNumSt.regNum[5] = regNum5;
    addrAndNumSt.regAddr[6] = regAddr6;
    addrAndNumSt.regNum[6] = regNum6;
    addrAndNumSt.regAddr[7] = regAddr7;
    addrAndNumSt.regNum[7] = regNum7;
    addrAndNumSt.regAddr[8] = regAddr8;
    addrAndNumSt.regNum[8] = regNum8;
    addrAndNumSt.regAddr[9] = regAddr9;
    addrAndNumSt.regNum[9] = regNum9;

    memset((u8 *)&protocolSt, 0, sizeof(protocolSt));
    protocolSt.head[0] = 0x62;
    protocolSt.head[1] = 0x6c;
    protocolSt.head[2] = 0x6d;
    protocolSt.addrSt.srcAddr = MAIN_BOARD_ADDR;
    protocolSt.addrSt.desAddr = RFID_ADDR;
    protocolSt.cmdSt.cmdCode = mcode;
    protocolSt.cmdSt.cmdAck = 0;
    protocolSt.cmdSt.cmdErrCode = 0;
    protocolSt.dataAreaNum = dataAreaNum;
    /* 如果是读指令 */
    if (0x03 == protocolSt.cmdSt.cmdCode)
    {
        protocolSt.dataAreaLen = 3 * dataAreaNum;
        dataAreaCount = 0;
        for (i = 0; i < dataAreaNum; i++)
        {
            protocolSt.dataArea[dataAreaCount++] = addrAndNumSt.regAddr[i] >> 8;
            protocolSt.dataArea[dataAreaCount++] = addrAndNumSt.regAddr[i];
            protocolSt.dataArea[dataAreaCount++] = addrAndNumSt.regNum[i];
        }
        protocolSt.dataArea[dataAreaCount++] = 0x6d;
        protocolSt.dataArea[dataAreaCount++] = 0x6c;
        protocolSt.dataArea[dataAreaCount++] = 0x62;
        bigSwapSmall((u8*)&protocolSt.dataAreaLen,1);
        crc = crc16((u8 *)&protocolSt, dataAreaCount + fr_dataAreaFront_len);
        protocolSt.dataArea[dataAreaCount++] = crc;
        protocolSt.dataArea[dataAreaCount++] = crc >> 8;
    }
    /* 如果是写指令 */
    else if (0x06 == protocolSt.cmdSt.cmdCode)
    {
        protocolSt.dataAreaLen = 0;
        dataAreaCount = 0;
        for (i = 0; i < dataAreaNum; i++)
        {
            protocolSt.dataAreaLen += (3 + addrAndNumSt.regNum[i] * 2);
            protocolSt.dataArea[dataAreaCount++] = addrAndNumSt.regAddr[i] >> 8;
            protocolSt.dataArea[dataAreaCount++] = addrAndNumSt.regAddr[i];
            protocolSt.dataArea[dataAreaCount++] = addrAndNumSt.regNum[i];
            for (j = 0; j < addrAndNumSt.regNum[i]; j++)
            {
                sys_read_vp(addrAndNumSt.regAddr[i] + j, (u8 *)&regValue, 1);

                if (addrAndNumSt.regAddr[i] >= 0x1000 && addrAndNumSt.regAddr[i] < 0x2000) /* 读写寄存器组 */
                {
                    pRegStAddr = (u8 *)&regSt.regRW + (addrAndNumSt.regAddr[i] + j - 0x1000) * 2;
                    // printf("pRegStAddr is %d\r\n", pRegStAddr);
                    // printf("regRW is %d\r\n", (u8 *)&regSt.regRW);
                    memmove(pRegStAddr, (u8*)&regValue, 2);
                }
                else if (addrAndNumSt.regAddr[i] >= 0x3000 && addrAndNumSt.regAddr[i] < 0x4000) /* 只写寄存器组 */
                {
                    pRegStAddr = (u8 *)&regSt.regW + (addrAndNumSt.regAddr[i] + j - 0x3000) * 2;
                    memmove(pRegStAddr, (u8*)&regValue, 2);
                }
                // printf("regAddr is %hd,regValue is %hd,aim:%hd\r\n", addrAndNumSt.regAddr[i] + j, regValue, regSt.regRW.aimedLight);
                // printf("addr:%hd ",addrAndNumSt.regAddr[i] + j);
                // printf("regValue:%hd \r\n",regValue);
                protocolSt.dataArea[dataAreaCount++] = regValue;
                protocolSt.dataArea[dataAreaCount++] = regValue >> 8;
            }
        }
        protocolSt.dataArea[dataAreaCount++] = 0x6d;
        protocolSt.dataArea[dataAreaCount++] = 0x6c;
        protocolSt.dataArea[dataAreaCount++] = 0x62;
        // printf("dataAreaCount is %hd", dataAreaCount);
        // printf("fr_dataAreaFront_len is %bd", fr_dataAreaFront_len);
        bigSwapSmall((u8*)&protocolSt.dataAreaLen,1);
        crc = crc16((u8 *)&protocolSt, dataAreaCount + fr_dataAreaFront_len);
        protocolSt.dataArea[dataAreaCount++] = crc;
        protocolSt.dataArea[dataAreaCount++] = crc >> 8;
    }
    else
    {
        protocolSt.dataAreaLen = 0;
        dataAreaCount = 0;
        protocolSt.dataArea[dataAreaCount++] = 0x6d;
        protocolSt.dataArea[dataAreaCount++] = 0x6c;
        protocolSt.dataArea[dataAreaCount++] = 0x62;
        bigSwapSmall((u8*)&protocolSt.dataAreaLen,1);
        crc = crc16((u8 *)&protocolSt, dataAreaCount + fr_dataAreaFront_len);
        protocolSt.dataArea[dataAreaCount++] = crc;
        protocolSt.dataArea[dataAreaCount++] = crc >> 8;
    }
    
    u2_send_bytes((u8 *)&protocolSt, dataAreaCount + fr_dataAreaFront_len);
}

/**
 * @start: **************************************************************
 * @author: chufengsen
 * @functhion:  协议处理函数
 * @description:
 * @param {*}
 * @return {*}
 * @end: ****************************************************************
 */
#if (USE_FREERTOS) /* 是否使用操作系统 */
extern xSemaphoreHandle regStDealMutex;
#endif
void protocol_thread(void)
{
    u8 *pStart = NULL, *pRecvBuf = NULL;
    u8 *pEnd = NULL;
    u16 recvDataLen = 0;
    u16 protocolDataLen = 0;
    u8 err_code = 0;

#if (USE_FREERTOS) /* 是否使用操作系统 */
    while (1)
    {
        xSemaphoreTake(serialSemaphoreHandle, portMAX_DELAY);
        xSemaphoreTake(regStDealMutex, portMAX_DELAY);
#else
    if (!get_recv_flag())
        return;

#endif
        pRecvBuf = get_recvBufPointer();
        recvDataLen = get_recv_dataLen();
        pStart = pRecvBuf;
        //printf("recv len is %hd\r\n",recvDataLen);
        while (recvDataLen) //连包处理，接收到连续包时可拆包
        {
            /* 包头判断和基本数据长度判断 */
            if (recvDataLen < 8 || find_fr_head_or_fr_end(pStart, fr_head, recvDataLen) == NULL)
            {
                break;
            }
            if (recvDataLen < 8 || find_fr_head_or_fr_end(pStart, fr_end, recvDataLen) == NULL)
            {
                break;
            }

            pStart = find_fr_head_or_fr_end(pStart, fr_head, recvDataLen);
            pEnd = find_fr_head_or_fr_end(pStart, fr_end, recvDataLen);
            protocolDataLen = (pEnd - pStart) + fr_dataAreaBack_len; //获取总包长
            //printf ("protocolDataLen is %hd ",protocolDataLen);
            if (!crc_check((u8 *)pStart, protocolDataLen))
            {
                err_code = ERR_CRC;
                memmove((u8 *)&protocolSt, pStart, protocolDataLen);
                break;
            }
            //printf ("protocolDataLen is %hd ",protocolDataLen);
            /* 结构体赋值 */
            memmove((u8 *)&protocolSt, pStart, fr_dataAreaFront_len);
            bigSwapSmall((u8*)&protocolSt.dataAreaLen,1);
            // printf ("DataLen is %hd ",protocolSt.dataAreaLen);
            // printf ("protocolDataLen is %hd ",protocolDataLen);
            memmove((u8 *)&protocolSt.dataArea, pStart + fr_dataAreaFront_len, protocolSt.dataAreaLen);
            // printf ("protocolDataLen is %hd ",protocolDataLen);
            // printf ("protocolDataLen is %hd ",protocolDataLen);
            /* 如果是应答包并且错误码不为0，即应答错误，在显示屏上显示错误内容 */
            if (protocolSt.cmdSt.cmdAck == 1 && protocolSt.cmdSt.cmdErrCode != ERR_NONE)
            {
                /* 在显示屏上显示错误内容 */
                //
                /* 指针偏移至当前完整包的包围，判断是否有下一包的数据 */
                pStart += protocolDataLen;
                /* 接收到的数据包总长度减去当前一包的数据长度 */
                recvDataLen -= protocolDataLen;
                break;
            }
            /* cmdAck错误 或者 目标地址不合法 */
            if (protocolSt.cmdSt.cmdErrCode != 0 || protocolSt.addrSt.desAddr != MAIN_BOARD_ADDR)
            {
                err_code = ERR_ADDR_CMD;
                break;
            }
            /* 数据域长度错误 */
            
            // printf ("protocolDataLen is %hd ",protocolDataLen);
            // printf ("protocolSt.cmdSt.cmdAck is %bd ",protocolSt.cmdSt.cmdAck);
            // printf ("protocolSt.cmdSt.code is %bd ",protocolSt.cmdSt.cmdCode);
            if ((protocolSt.dataAreaLen + fr_dataAreaFront_len + fr_dataAreaBack_len) != protocolDataLen)
            {
                err_code = ERR_LEN;
                break;
            }
            
            err_code = protocol_recv_deal();
            
            // printf ("err_code is %bd\r\n",err_code);
            if (err_code != ERR_NONE)
            {
                break;
            }
            serial_recv_response(err_code);
            pStart += protocolDataLen;
            recvDataLen -= protocolDataLen;
        }
        if (err_code != ERR_NONE)
            serial_recv_response(err_code);
        recv_restart();
#if (USE_FREERTOS)
        xSemaphoreGive(regStDealMutex);
    }
#endif
}
